#include "FileCobertura.h"
#include "Solucao.h"

using namespace std;

FileCobertura::FileCobertura() {
}

/*double FileCobertura::distanciaClientSteiner(int indS, int indC){
        //F�rmula Euclidiana
        double quad_x = sqr(xSteiner[indS] - xClient[indC]);
        //printf("xS %d, xC %d\n", xSteiner[indC], xClient[indS]);
        double quad_y = sqr(ySteiner[indS] - yClient[indC]);
        //printf("yS %d, yC %d\n", ySteiner[indC], yClient[indS]);
        return sqrt(quad_x + quad_y);// + 0.5;
}*/

void FileCobertura::loadFile(char *name) {
    FILE *pf;
    //char *n = new char[strlen(IN_PATH) + strlen(name) + strlen("tipo_") + 1];
    char n[100];
    strcpy(n, IN_PATH);
    strcat(n, name);
    strcat(n, "_distancias.txt");
    if ((pf = fopen(n, "r")) == NULL) {
        printf("\nNao consigo abrir o arquivo %s! ", n);
        exit(1);
    }
    //Carregando o cabecalho do arquivo
    /*fscanf(pf, "%*s %*s %*s");//--- NAME : f10_4.rcp
    fscanf(pf, "%*s %*s %*s %*s %*s");//--- COMMENT : problem instance
    fscanf(pf, "%*s %*s %*s");//--- TYPE : TSP
    fscanf(pf, "%*s %*s %d",&tamSteiner);//--- DIMENSION : n
    tamClient = tamSteiner;
  			
    fscanf(pf, "%*s %*s %*s");//--- EDGE_WEIGHT_TYPE : EUC_2D
    fscanf(pf, "%*s");//--- NODE_COORD_SECTION

    xSteiner = new double[tamSteiner];
    ySteiner = new double[tamSteiner];
                
    xClient = new double[tamClient];
    yClient = new double[tamClient];
			
    double x,y;
    for(int i=0, j=0; i < tamSteiner; i++){
            fscanf(pf, "%d %Le %Le", &j, &x, &y);
            xClient[i] = xSteiner[i] = x;
            yClient[i] = ySteiner[i] = y;
            //printf("N: %d - X: %Le - Y: %Le \n", j, xClient[i], yClient[i]);exit(0);
    }*/

    fscanf(pf, "%d", &V);
    F = V;

    //printf("V: %d - F: %d\n", V, F);

    this->distances = new double*[V];
    this->type = new int[F];
    this->demanda = new int[V];
    double a;
    for (int i = 0; i < V; i++) {
        this->distances[i] = new double[F];
        for (int j = 0; j < F; j++) {
            fscanf(pf, "%lf", &a);
            this->distances[i][j] = a;
            //printf("D: %lf", distances[i][j]);
        }
    }
    fclose(pf);
    //FileCobertura::calculateDist();

    //Lendo arquivo das demandas
    strcpy(n, IN_PATH);
    strcat(n, name);
    strcat(n, "_demandas.txt");
    if ((pf = fopen(n, "r")) == NULL) {
        for (int i = 0; i < V; i++) {
            this->demanda[i] = 1;
        }

    } else {
        for (int i = 0; i < V; i++) {
            fscanf(pf, "%d", &this->demanda[i]);
        }

        fclose(pf);
    }

    //Lendo arquivo dos tipos
    strcpy(n, IN_PATH);
    strcat(n, name);
    strcat(n, "_tipos.txt");

    if ((pf = fopen(n, "r")) == NULL) {
        for (int i = 0; i < F; i++) {
            this->type[i] = Solucao::CLIENT_FACILITY;
        }

    } else {
        for (int i = 0; i < F; i++) {
            fscanf(pf, "%d", &this->type[i]);
        }

        fclose(pf);
    }
    //delete n;
    //puts("FIM");
}

/*void FileCobertura::calculateDist(){
       this->distances = new double*[tamSteiner];
       for(int i=0; i < tamSteiner; i++){
                       this->distances[i] = new double[tamSteiner];
               for(int j=0; j < tamSteiner; j++){
                                   distances[i][j] = this->distanciaClientSteiner(i, j);
               }
       }
}*/

void FileCobertura::printInstancia(double alpha, int n, int m, double mbest, double z, double mtempo, int melhorTodas, int piorTodas) {
    FILE *pf;
    char *nn = new char[100];
    sprintf(nn, "%s%s%1.1f%s", OUT_PATH, "/solver_result_", alpha, ".txt");
    if ((pf = fopen(nn, "a")) == NULL) {
        printf("\nNao consigo abrir o arquivo instancias.txt!");
        exit(1);
    }
    //puts("write");
    fprintf(pf, "%d\t%d\t%lf\t%f\t%lf\t%8d\t%8d\n", n, m, mbest, z, mtempo, melhorTodas, piorTodas);
    
    printf("Instance\tFacilities\tDistance\t        Objetive\tTotal time\n");
    printf("%8d\t%10d\t%8lf\t%16.2f\t%10lf\t%8d\t%8d\n", n, m, mbest, z, mtempo, melhorTodas, piorTodas);

    fclose(pf);
    delete nn;
}

void FileCobertura::readXML() {
    puts("REadXML");
    std::string file("scenario.xml");
    jcommon::XmlDocument doc;
    doc.LoadFile("scenario.xml");
    puts("REadXML");

    int numVehicle = 0;
    int typesVehicle = 0;

    jcommon::XmlElement* root = doc.RootElement();
    if (root) {
        jcommon::XmlElement* vehicle = root->FirstChildElement("vehicle");
        if (vehicle) {
            do {
                ++typesVehicle;
                numVehicle += atoi(vehicle->Attribute("numVehicles"));
            } while (vehicle = vehicle->NextSiblingElement("vehicle"));
        }

        vehicle = root->FirstChildElement("vehicle");
        if (vehicle) {
            do {
                printf("%s\n", vehicle->Attribute("capacity"));
                printf("%s\n", vehicle->Attribute("numVehicles"));
                printf("%s\n", vehicle->Attribute("fixCost"));
                printf("%s\n", vehicle->Attribute("depCost"));
            } while (vehicle = vehicle->NextSiblingElement("vehicle"));
        }

    }

    printf("Types of Vehicle: %d\n", typesVehicle);
    printf("Num of Vehicle: %d\n", numVehicle);

}

void FileCobertura::writeXML(SolucaoGRASPCobertura *sol, long tempo) {
    //Abrir o diretorio com as dimensoes da solucao.
    //char *n = new char[strlen(OUT_PATH) + strlen("solucao.xml")+1];
    //strcpy(n, IN_PATH);
    //strcat(n, "solucao.xml");n[strlen(n)]='\0';
    std::string file("data/saida/solucao.xml");
    jcommon::XmlDocument doc(file);
    //jcommon::XmlDocument doc("saida/solucao.xml");
    //delete n;
    char data[200];
    jcommon::XmlElement *solucao = new jcommon::XmlElement("map");
    //Inserindo o OPT.
    jcommon::XmlElement opt("opt");
    if (sol == NULL) {
        //solucao->InsertEndChild(opt);
        doc.LinkEndChild(solucao);
        doc.SaveFile();
        return;
    }

    double sum_dist = 0;
    double max_dist = 0;
    for (int n = 0; n < Solucao::V; ++n) {
        if (sol->c[n] >= 0) {
            sum_dist += sol->linkClient[n][sol->c[n]];
            if (sol->linkClient[n][sol->c[n]] > max_dist)
                max_dist = sol->linkClient[n][sol->c[n]];
        }
    }
    sprintf(data, "%d", sol->avaliacao);
    opt.SetAttribute("demand", data);

    sprintf(data, "%f", Solucao::D);
    opt.SetAttribute("cobertura", data);

    sprintf(data, "%f", sum_dist);
    opt.SetAttribute("sum_dist", data);

    sprintf(data, "%f", max_dist);
    opt.SetAttribute("max_dist", data);


    sprintf(data, "%ld", tempo);
    opt.SetAttribute("time_proc", data);
    solucao->InsertEndChild(opt);

    //Inserindo os Nodes
    for (int n = 0; n < Solucao::V; ++n) {
        jcommon::XmlElement node("node");
        sprintf(data, "%d", n);
        node.SetAttribute("id", data);
        if (sol->solucao[n] == true) {
            sprintf(data, "%s", "true");
        } else {
            sprintf(data, "%s", "false");
        }
        node.SetAttribute("facility", data);

        if (sol->c[n] >= 0) {
            sprintf(data, "%d", sol->c[n]);
            node.SetAttribute("atri", data);
            sprintf(data, "%f", Solucao::linkClient[n][sol->c[n]]);
            node.SetAttribute("dist", data);
        } else {
            sprintf(data, "%d", -1);
            node.SetAttribute("atri", data);
            node.SetAttribute("dist", data);
        }
        solucao->InsertEndChild(node);
    }
    doc.LinkEndChild(solucao);
    doc.SaveFile();
}

FileCobertura::~FileCobertura() {

    if (distances) {
        for (int i = 0; i < V; i++) {
            delete distances[i];
        }
        delete distances;
    }

    if (type)
        delete type;
    if (demanda)
        delete demanda;

    /*if(xSteiner)
        delete xSteiner;
    if(ySteiner)
        delete ySteiner;
    if(xClient);
        delete xClient;
    if(yClient)
        delete yClient;*/
}
